#-*- coding:utf-8 -*-
try:
    from PIL import Image
    from PIL.ExifTags import TAGS as _tags,GPSTAGS as _gpstags
except:
    print "PIL or pillow needed!!!!!!"
try:
    from Tkinter import Frame,Text,Button,Label,Entry,StringVar,Tk,Checkbutton,LEFT,W,OptionMenu
    import tkFileDialog,tkFont
except:
    print "Warn:Gui will fail without tkinter lib"
import gettext,os,sys,datetime,time,thread,csv,glob
Kml='<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">{document}</kml>'
Document='<Document><Style id="style_a"><IconStyle><scale>1</scale><Icon><href>http://maps.google.com/mapfiles/kml/shapes/airports.png</href></Icon><hotSpot x="20" y="20" xunits="pixels" yunits="pixels"/></IconStyle><LineStyle><color>7fff5555</color><width>5</width></LineStyle></Style>{placemarks}</Document>'
PlaceMark='<Placemark><name>{img_name}</name><description><p>Image Path:{img_path}</p><p>Image Time:{img_time}</p></description><styleUrl>#style_a</styleUrl><Point><coordinates>{lng},{lat},{alt}</coordinates></Point></Placemark>'
LineMark='<Placemark><name>...</name><styleUrl>#m_ylw-pushpin</styleUrl><LineString><tessellate>1</tessellate><coordinates>{coord}</coordinates></LineString></Placemark>'
gps_item=34853#I don't know why,I just try it out
img_ctime=306#Same as previous
def _(text):
    return text
def sleep_and_wake(sv,text,time_pass):
    time.sleep(time_pass)
    sv.set(text)
def flash_message(string_val,new_value,origin=None,time_pass=3):
    if not origin:
        origin=string_val.get()
    string_val.set(new_value)
    thread.start_new_thread(sleep_and_wake,(string_val,origin,time_pass))
def read_pics_gps_info(_path,include_all=True):
    '''
    return:[(pic_name,path,latitude,longitude,altitude,time),(pic...)...]
    '''
    rlt=[]
    pic_count=0
    for cur,ds,fs in os.walk(_path):
        if os.path.split(cur)[-1].startswith("#"):
            continue
        for f in fs:
            if f[-3:].lower() in ("jpg","jpeg"):
                try:
                    img_info=[f,os.path.join(os.path.normpath(cur),f)]
                    img=Image.open(img_info[-1])
                    exif_info=img._getexif()
                    #for k,v in exif_info.items():
                    #    try:
                    #        print _tags[k],k,v
                    #    except:
                    #        print "----",k,v
                    gps=exif_info[gps_item]
                    for i in range(1,3):
                        img_info.append("{0}{1}".format(gps[i*2][0][0]+gps[2*i][1][0]*1./60+gps[2*i][2][0]*1./gps[2*i][2][1]/3600,gps[1]))
                    img_info.append(str(gps[6][0]*1./gps[6][1]))
                    img_info.append(datetime.datetime.strptime(exif_info[img_ctime],"%Y:%m:%d %H:%M:%S"))
                    rlt.append(tuple(img_info))
                    del img_info
                except:
                    pass
                finally:
                    pic_count+=1
    return sorted(rlt,lambda x,y:cmp(x[-1],y[-1])),pic_count
def make_kml(target,points):
    if not target.endswith("kml"):
        target+=".kml"
    pms=[]
    for point in points:
        pt_text=PlaceMark.format(img_name=point[0],lat=point[2],lng=point[3],alt=point[4],img_path=os.path.join(point[1],point[0]),img_time=str(point[5]))
        pms.append(pt_text)
    try:
        with open(target,"w") as f:
            f.write(Kml.format(document=Document.format(placemarks="".join(pms))))
        return True
    except:
        return False
class Config:
    title=_("KmlFromPics")
    input_dir=_("InputDir")
    output_file=_("OutPut")
    but1_msg=_("Choose")
    but2_msg=_("Choose")
    openfile_title=_("OpenFile")
    savefile_title=_("SaveAs")
    savefile_no_title=_("Make?")
    savefile_ask=_("No dir was there,make it?")
    select_dir=_("Select Pictures Directory")
    ask_exist=_("Exist already,overwrite?")
    ready=_("Ready!")
    include_sub_dir=_("Sub dirs included")
    win_width=1000
    win_height=50
    dialog_width=500
    dialog_height=120
class Application(Frame):
    def __init__(self,master=None):
        Frame.__init__(self,master)
        toplevel=self.winfo_toplevel()
        toplevel.title(Config.title)
        toplevel.resizable(False,False)
        toplevel.geometry("{0}x{1}+{2}+{3}".format(Config.win_width,Config.win_height,toplevel.winfo_screenwidth()/2-Config.win_width/2,toplevel.winfo_screenheight()/2-Config.win_height))
        self.from_dir=StringVar(self,value=os.getcwd())
        self.grid()
        self.init_var()
        self.init_ui()
    def init_var(self):
        self.state_text=StringVar(self,value=Config.ready)
        self.pic_infos=[]
        self.init_dir=os.getcwd()
    def init_ui(self):
        self.label1=Label(self,text=Config.input_dir,width=10)
        self.label1.grid(column=0,row=0)
        self.entry=Entry(self,textvariable=self.from_dir,width=50)
        self.entry.grid(column=1,row=0)
        self.button1=Button(self,text=Config.but1_msg,width=15,command=self.choose_dir)
        self.button1.grid(column=3,row=0)
        self.button2=Button(text="Save",width=15,command=self.choose_save_file)
        self.button2.grid(column=4,row=0)
        self.check=Checkbutton(self,text=Config.include_sub_dir)
        self.check.grid(column=2,row=0)
        self.check.select()
        self.label_state=Label(self,textvariable=self.state_text,fg="#ff0000",font=tkFont.Font(size=8),justify=LEFT)
        self.label_state.grid(column=0,row=2,columnspan=3,sticky=W)
    def _thread_read_pics(self,rlt):
        self.pic_infos,c=read_pics_gps_info(rlt)
        self.state_text.set("{0}/{1} infos".format(len(self.pic_infos),c))
    def choose_dir(self):
        if os.path.exists(self.entry.get()):
            self.init_dir=self.entry.get()
        rlt=tkFileDialog.askdirectory(title=Config.select_dir,initialdir=self.init_dir)
        if rlt:
            self.from_dir.set(rlt)
            thread.start_new_thread(self._thread_read_pics,(rlt,))
            self.state_text.set("Reading...")
    def choose_save_file(self):
        if not len(self.pic_infos):
            flash_message(self.state_text,"No GPS info found in pictures!")
            return None
        how=False
        rlt=tkFileDialog.asksaveasfilename(title=Config.savefile_title,initialdir=self.entry.get(),initialfile=os.path.basename(self.entry.get())+"_"+datetime.datetime.now().strftime("%Y%m%d%H%M%S")+".kml",filetypes=[("kml",".kml")])
        if rlt:
            if not rlt.endswith("kml"):
                rlt+=".kml"
            if os.path.exists(rlt):
                save_rlt=tkMessageBox.askquestion(title="Want?",message=Config.ask_exist)
                if save_rlt:
                    how=make_kml(rlt,self.pic_infos)
                else:
                    self.choose_save_file()
            else:
                how=make_kml(rlt,self.pic_infos)
        if how:
            flash_message(self.state_text,"Make Success",Config.ready)#self.state_text.set("Make Success")
        else:
            flash_message(self.state_text,"Make Fail or Canceled")
class PickDialog(Frame):
    def __init__(self,parent):
        Frame.__init__(self,parent)
        toplevel=self.winfo_toplevel()
        toplevel.title("Pick")
        toplevel.resizable(True,False)
        toplevel.geometry("{0}x{1}+{2}+{3}".format(Config.dialog_width,Config.dialog_height,toplevel.winfo_screenwidth()/2-Config.dialog_width/2,toplevel.winfo_screenheight()/2-Config.dialog_height))
        self.grid()
        self.title=("None","Name","FilePath","Latitude","Longitude","Altitude","Time")
    def init_ui(self,csv_reader):
        self.reader=[]
        _row=[]
        menus=[]
        self.menu_text=[]
        for row in csv_reader:
            if row:
                self.reader.append(row)
                if not _row:
                    _row=row
        if _row:
            Label(self,text="Choose every column's meaning",fg="#0000ee").grid(column=0,row=0,columnspan=len(_row))
            for index,col in enumerate(_row):
                v=StringVar()
                v.set(self.title[0])
                self.menu_text.append(v)
                menu=OptionMenu(self,v,*self.title)
                menu.grid(row=2,column=index)
                menu.grid_propagate(0)
                menus.append(menu)
                label=Label(self,text=col)
                label.grid(row=1,column=index)
            self.but=Button(self,text="Choose",command=self.but_click,width=len(_row)*15)
            self.but.grid(row=3,column=0,columnspan=len(_row))
    def but_click(self):
        rlt={}
        pic_infos=[]
        for ix,_str in enumerate([x.get() for x in self.menu_text]):
            if _str!=self.title[0]:
                rlt[_str]=ix
        for row in self.reader:
            items=["" for i in range(len(self.title)-1)]
            for ix in range(len(self.title)-1):
                if self.title[ix] in rlt:
                    items[ix]=row[rlt[self.title[ix]]]
            pic_infos.append(tuple(items))
        save_path=os.path.dirname(sys.argv[1])
        final_target=os.path.join(save_path,os.path.basename(sys.argv[1]))
        try:
            max_num=max([int(os.path.split(x)[1].split(".")[-2]) for x in glob.glob(final_target+"*")])
        except:
            max_num=-1
        make_kml(final_target+"."+str(max_num+1),pic_infos)#datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
if __name__=="__main__":
    '''
    for pic:
        GUI:Click the file
        Command:%1 dir_path
    for csv file:
        GUI:%1 csv_full_path
        Command %1 csv_full_path name,lat,lng,alt
    '''
    if len(sys.argv)==1:
        tk=Tk()
        app=Application(tk)
        app.mainloop()
    elif len(sys.argv)>1:
        if os.path.isfile(sys.argv[1]):
            with open(sys.argv[1],'r') as f:
                reader=csv.reader(f)
                if(len(sys.argv)==2):
                    tk=Tk()
                    dialog=PickDialog(tk)
                    dialog.init_ui(reader)
                    dialog.mainloop()
                elif len(sys.argv)==3:
                    pic_infos=[]
                    cols=sys.argv[2].split(",")
                    
                    for row in reader:
                        pic_infos.append((row[cols.index("name")],"",row[1],row[0],"",""))
                    save_path=os.path.dirname(sys.argv[1])
                    final_target=os.path.join(save_path,os.path.basename(sys.argv[1]))
                    try:
                        max_num=max([int(os.path.split(x)[1].split(".")[-2]) for x in glob.glob(final_target+"*")])
                    except:
                        max_num=-1
                    make_kml(final_target+"."+str(max_num+1),pic_infos)#datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
        elif os.path.isdir(sys.argv[1]):
            pic_infos=read_pics_gps_info(sys.argv[1])[0]
            save_path=sys.argv[1]
            final_target=os.path.join(save_path,os.path.basename(sys.argv[1]))
            try:
                max_num=max([int(os.path.split(x)[1].split(".")[-2]) for x in glob.glob(final_target+"*")])
            except:
                max_num=-1
            make_kml(final_target+"."+str(max_num+1),pic_infos)#datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
